#ifndef __CONTEXTO_H__
#define __CONTEXTO_H__
#ifndef NULL
#define NULL 0
#endif
#include "Modelo.h"
#include <list>

class Contexto
{

    public:

    typedef std::list<Simbolo> ValorContexto;
    typedef std::list<Modelo *> ListadoModelos;
    typedef unsigned char Orden;

    /**
    * @param orden Indica la cantidad de simbolos que se deben tener en cuenta 
    * en el valor del contexto.
    * @param modeloCero Modelo a utilizar en el modelo cero y como instancia
    * cradora de los modelos de siguientes órdenes.
    */
    Contexto(Orden orden,Modelo *modeloCero=NULL);

    ~Contexto();
    
    /**
    * Agrega un simbolo al final del valor del contexto y se encarga de 
    * eliminar el primer simbolo del valor del contexto en caso de 
    * corresponder.
    * @param simbolo Simbolo a ser agregado.
    */
    void addSimbolo(const Simbolo simbolo);
    
    /**
    * Obtiene un listado de los modelos que deben ser consultados ordenados 
    * por su Orden de menor a mayor segun el valor del contexto actual.
    */
    ListadoModelos &getModelos();
    
    /**
     * Para el contexto actual devuelve el modelo de mayor orden, e inicializa
     * la iteración hacia atrás. Para obtener los sucesivos modelos, hasta el
     * modelo cero, para el contexto actual, llamar a getModeloAnteriorOrden.
     * @return Modelo de mayor orden.
     */
    Modelo *getModeloMayorOrden();

    /**
     * @pre Antes de llamar este método debe haber sido llamado el método
     * getModeloMayorOrden.
     * Llamado sucecivas veces luego de llamar getModeloMayorOrden. Va obteniendo
     * con cada llamado un modelo de orden anterior hasta devolver el modelo cero
     * y finalmente con la última llamada devolvera null.
     * @return Modelo de orden menor al obtenido con getModeloMayorOrden o
     * getModeloAnteriorOrden
     */
    Modelo *getModeloAnteriorOrden();

    private:
    
    Orden orden;
    Modelo *modeloCero;
    ValorContexto valorContexto;
    
    // Utilizada por getModeloMayorOrden y getModeloAnteriorOrden
    ValorContexto valorContextoRecorrido;

    // Listado de modelos a ser pasado por referencia por algunos métodos.
    ListadoModelos listadoModelos;
    // Indicador para ver si ya se devolvió el modelo cero en el recorrido.
    bool modeloCeroYaDevuelto;
    
    /**
    * @pre Debe existir el camino de simbolos indicado por valorContexto en 
    * el arbol de modelos.
    * Devuelve el modelo para el valor del contexto. Siempre devuelve el modelo.
    * Si no existe lo crea en las estructura de modelos.
    * @param valorContexto Camino a seguir en el arbol de modelos.
    */
    Modelo *getModelo(const ValorContexto &valorContexto);

};

#endif

